package cn.com.xy.sms.sdk.number;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONObject;

import android.content.Context;
import android.util.Pair;
import cn.com.xy.sms.sdk.Iservice.XyCallBack;
import cn.com.xy.sms.sdk.constant.Constant;
import cn.com.xy.sms.sdk.db.entity.NumberInfo;
import cn.com.xy.sms.sdk.log.LogManager;
import cn.com.xy.sms.sdk.net.NetUtil;
import cn.com.xy.sms.sdk.util.CallBackState;
import cn.com.xy.sms.sdk.util.FileUtils;
import cn.com.xy.sms.sdk.util.StringUtils;
import cn.com.xy.sms.sdk.util.ThreadPoolManager;
import cn.com.xy.sms.sdk.util.XyUtil;

/* SDK-428 huangzhiqiang 20160615 start */
public class NumberLogoUtil {
    public static final String DOWNLOAD_IN_THREAD_POOL = "DownloadInThreadPool";
    // logo名称对应logo下载请求时间，用于判断是否重复请求下载
    private static final HashMap<String, Long> LAST_DOWNLOAD_LOGO_TIME = new HashMap<String, Long>();

    public static final String UNION_LOGO_NAME_START = "duoqu_mobile_"; // 联盟logo名称开头

    private static boolean isUnionLogo(String logoName) {
        /*SDK-637 zhaojiangwei 20160929 start*/
        if(logoName == null){
            return false;
        }
        /*SDK-637 zhaojiangwei 20160929 end*/
        return logoName.toLowerCase().startsWith(UNION_LOGO_NAME_START);
    }

    private static boolean isUnionServer(String serverUrl) {
        return !NetUtil.BIZPORT_DOWN_URL.equals(serverUrl);
    }

    /**
     * 获取数据源提供商logo
     * 
     * @param ctx
     * @param num 号码
     * @param extend 扩展参数
     * @param callBack 
     *            index0(状态，一般只需关注CURRENT_THREAD_HAS_DATA、DOWNLOAD_COMPLETE这两个状态 ): 
     *                  CallBackState.CURRENT_THREAD_HAS_DATA:当前线程，存在logo文件
     *                  CallBackState.CURRENT_THREAD_REPEAT_REQUEST:当前线程，重复logo下载请求
     *                  CallBackState.CURRENT_THREAD_NEED_DOWNLOAD:当前线程，需要下载logo文件
     *                  CallBackState.DOWNLOAD_COMPLETE:当前线程或新线程，成功下载文件
     *                  CallBackState.DOWNLOAD_FAILED:当前线程或新线程，文件下载失败
     *                  CallBackState.ERROR:当前线程或新线程，存在异常，文件下载失败
     *            index1:logoName
     *            index2:
     *                  (index0 == CallBackState.DOWNLOAD_COMPLETE):文件的File对象
     *                  (index0 == CallBackState.DOWNLOAD_FAILED):"download failed"
     *                  (index0 == CallBackState.ERROR):String类型 异常信息
     * @return
     */
    public static File findUnionLogoFile(Context ctx, final String num, Map<String, String> extend,
            final XyCallBack callBack) {
        JSONObject numInfo = ParseNumberCache.queryByNum(num);
        if (numInfo == null) {
            XyUtil.doXycallBackResult(callBack, CallBackState.ERROR, num, "no num data");
            return null;
        }

        String unionLogoName = null;
        if (isAuth(numInfo)) {
            unionLogoName = UNION_LOGO_NAME_START + numInfo.optString("src") + ".png";
        } else {
            // 非认证号码以后可能要显示其他logo
            unionLogoName = UNION_LOGO_NAME_START + numInfo.optString("src") + ".png";
        }
        return findLogoFile(ctx, NetUtil.BIZPORT_DOWN_URL, unionLogoName, extend, downLogoFileCallBack(num, callBack));
    }

    /**
     * 是否认证号码
     * 
     * @param numInfo
     * @return true:是 false:否
     */
    private static boolean isAuth(JSONObject numInfo) {
        return "1".equals(numInfo.optString(NumberInfo.AUTH_KEY));
    }

    /**
     * 获取号码logo
     * 
     * @param ctx
     * @param num 号码
     * @param extend 扩展参数
     * @param callBack 
     *            index0(状态，一般只需关注CURRENT_THREAD_HAS_DATA、DOWNLOAD_COMPLETE这两个状态): 
     *                  CallBackState.CURRENT_THREAD_HAS_DATA:当前线程，存在logo文件
     *                  CallBackState.CURRENT_THREAD_REPEAT_REQUEST:当前线程，重复logo下载请求
     *                  CallBackState.CURRENT_THREAD_NEED_DOWNLOAD:当前线程，需要下载logo文件
     *                  CallBackState.DOWNLOAD_COMPLETE:当前线程或新线程，成功下载文件
     *                  CallBackState.DOWNLOAD_FAILED:当前线程或新线程，文件下载失败
     *                  CallBackState.ERROR:当前线程或新线程，存在异常，文件下载失败
     *            index1:num
     *            index2:
     *                  (index0 == CallBackState.DOWNLOAD_COMPLETE):文件的File对象
     *                  (index0 == CallBackState.DOWNLOAD_FAILED):"download failed"
     *                  (index0 == CallBackState.ERROR):String类型 异常信息
     * @return
     */
    public static File findLogoFile(final Context ctx, final String num, Map<String, String> extend,
            final XyCallBack callBack) {
        try {
            JSONObject numInfo = ParseNumberCache.queryByNum(num);
            if (numInfo == null) {
                XyUtil.doXycallBackResult(callBack, CallBackState.ERROR, num, "no num data");
                return null;
            }

            String logoNameOrLogoDownloadUrl = numInfo.optString(NumberInfo.LOGO_KEY);
            if (StringUtils.isNull(logoNameOrLogoDownloadUrl)) {
                XyUtil.doXycallBackResult(callBack, CallBackState.ERROR, num, "logo is null");
                return null;
            }

            String serverUrl = null;
            String logoName = null;
            boolean isLogoDownloadUrl = logoNameOrLogoDownloadUrl.toLowerCase().startsWith("http");
            if (isLogoDownloadUrl) {
                Pair<String, String> serverUrlAndlogoNamePair = getServerUrlAndlogoNamePair(numInfo);
                serverUrl = serverUrlAndlogoNamePair.first;
                logoName = serverUrlAndlogoNamePair.second;
            } else {
                serverUrl = NetUtil.BIZPORT_DOWN_URL;
                logoName = logoNameOrLogoDownloadUrl;
            }

            return findLogoFile(ctx, serverUrl, logoName, extend, downLogoFileCallBack(num, callBack));
        } catch (Throwable e) {
            LogManager.e(Constant.TAG, "NumberLogoUtil findLogoFile 2 error:", e);
            XyUtil.doXycallBackResult(callBack, CallBackState.ERROR, num, e.getMessage());
        }
        return null;
    }
    /*SDK-637 zhaojiangwei 20160929 start*/
    public static File findLogoFile(Context ctx, String num, Map<String, String> extend) {
        try {
            JSONObject numInfo = ParseNumberCache.queryByNum(num);
            if (numInfo == null) {
                return null;
            }

            String logoNameOrLogoDownloadUrl = numInfo.optString(NumberInfo.LOGO_KEY);
            if (StringUtils.isNull(logoNameOrLogoDownloadUrl)) {
                return null;
            }

            String logoName = null;
            boolean isLogoDownloadUrl = logoNameOrLogoDownloadUrl.toLowerCase().startsWith("http");
            if (isLogoDownloadUrl) {
                Pair<String, String> serverUrlAndlogoNamePair = getServerUrlAndlogoNamePair(numInfo);
                logoName = serverUrlAndlogoNamePair.second;
            }
            else {
                logoName = logoNameOrLogoDownloadUrl;
            }

            File file = getLocalLogoFile(logoName);
            // 本地已存在图片文件
            if (file != null) {
                return file;
            }
        }
        catch (Throwable e) {
            LogManager.e(Constant.TAG,
                    "NumberLogoUtil findLogoFile(Context ctx, String num, Map<String, String> extend) error:", e);
        }
        return null;
    }

    public static File findLogoFileByNet(Context ctx, String num, Map<String, String> extend) {
        try {
            JSONObject numInfo = ParseNumberCache.queryByNum(num);
            if (numInfo == null) {
                return null;
            }

            String logoNameOrLogoDownloadUrl = numInfo.optString(NumberInfo.LOGO_KEY);
            if (StringUtils.isNull(logoNameOrLogoDownloadUrl)) {
                return null;
            }

            String serverUrl = null;
            String logoName = null;
            boolean isLogoDownloadUrl = logoNameOrLogoDownloadUrl.toLowerCase().startsWith("http");
            if (isLogoDownloadUrl) {
                Pair<String, String> serverUrlAndlogoNamePair = getServerUrlAndlogoNamePair(numInfo);
                serverUrl = serverUrlAndlogoNamePair.first;
                logoName = serverUrlAndlogoNamePair.second;
            }
            else {
                serverUrl = NetUtil.BIZPORT_DOWN_URL;
                logoName = logoNameOrLogoDownloadUrl;
            }

            return findLogoFile(ctx, serverUrl, logoName, extend, null);
        }
        catch (Throwable e) {
            LogManager.e(Constant.TAG, "NumberLogoUtil findLogoFileByNet error:", e);
        }
        return null;
    }
    /*SDK-637 zhaojiangwei 20160929 end*/
    private static Pair<String, String> getServerUrlAndlogoNamePair(JSONObject numInfo) {
        if (numInfo == null || numInfo.length() == 0) {
            return null;
        }
        try {
            Pair<String, String> serverUrlAndlogoNamePair = createServerUrlAndlogoNamePairByCache(numInfo);
            if (serverUrlAndlogoNamePair == null) {
                String logoDownloadUrl = numInfo.optString(NumberInfo.LOGO_KEY);
                serverUrlAndlogoNamePair = createServerUrlAndlogoNamePairByLogoDownloadUrl(logoDownloadUrl);
                if (serverUrlAndlogoNamePair != null) {
                    // 缓存下载服务器和logo名称
                    numInfo.put(NumberInfo.SERVER_URL_KEY, serverUrlAndlogoNamePair.first);
                    numInfo.put(NumberInfo.LOGO_NAME_KEY, serverUrlAndlogoNamePair.second);
                }
            }
            return serverUrlAndlogoNamePair;
        } catch (Throwable e) {
            LogManager.e(Constant.TAG, "NumberLogoUtil getServerUrlAndlogoNamePair error:", e);
        }
        return null;
    }

    private static Pair<String, String> createServerUrlAndlogoNamePairByCache(JSONObject numInfo) {
        if (numInfo == null) {
            return null;
        }
        boolean hasCache = numInfo.has(NumberInfo.SERVER_URL_KEY) && numInfo.has(NumberInfo.LOGO_NAME_KEY);
        if (!hasCache) {
            return null;
        }
        String serverUrl = numInfo.optString(NumberInfo.SERVER_URL_KEY);
        String logoName = numInfo.optString(NumberInfo.LOGO_NAME_KEY);
        return new Pair<String, String>(serverUrl, logoName);
    }

    private static Pair<String, String> createServerUrlAndlogoNamePairByLogoDownloadUrl(String logoDownloadUrl) {
        if (StringUtils.isNull(logoDownloadUrl)) {
            return null;
        }
        int serverUrlEndIndex = logoDownloadUrl.lastIndexOf("/");
        String serverUrl = logoDownloadUrl.substring(0, serverUrlEndIndex + 1);
        String logoName = logoDownloadUrl.substring(serverUrlEndIndex + 1);
        return new Pair<String, String>(serverUrl, logoName);
    }

    /**
     * 
     * @param ctx
     * @param serverUrl
     * @param logoName logo图片名称
     * @param extend 扩展参数
     * @param callBack 
     *            index0(状态，一般只需关注CURRENT_THREAD_HAS_DATA、DOWNLOAD_COMPLETE这两个状态): 
     *                  CallBackState.CURRENT_THREAD_HAS_DATA:当前线程，存在logo文件
     *                  CallBackState.CURRENT_THREAD_REPEAT_REQUEST:当前线程，重复logo下载请求
     *                  CallBackState.CURRENT_THREAD_NEED_DOWNLOAD:当前线程，需要下载logo文件
     *                  CallBackState.DOWNLOAD_COMPLETE:当前线程或新线程，成功下载文件
     *                  CallBackState.DOWNLOAD_FAILED:当前线程或新线程，文件下载失败
     *                  CallBackState.ERROR:当前线程或新线程，存在异常，文件下载失败
     *            index1:logoName
     *            index2:
     *                  (index0 == CallBackState.DOWNLOAD_COMPLETE):文件的File对象
     *                  (index0 == CallBackState.DOWNLOAD_FAILED):"download failed"
     *                  (index0 == CallBackState.ERROR):String类型 异常信息
     * @return
     */
    private static File findLogoFile(final Context ctx, final String serverUrl, final String logoName,
            Map<String, String> extend, final XyCallBack callBack) {
        try {
            File file = getLocalLogoFile(logoName);
            // 本地已存在图片文件
            if (file != null) {
                XyUtil.doXycallBackResult(callBack, CallBackState.CURRENT_THREAD_HAS_DATA, logoName, file);
                return file;
            }

            // 记录最后下载时间失败代表还没过下载间隔，直接返回
            if (!addLastDownloadLogoTime(logoName)) {
                XyUtil.doXycallBackResult(callBack, CallBackState.CURRENT_THREAD_REPEAT_REQUEST, logoName,
                        "repeat request");
                return null;
            }

            // 在线程池的线程内执行下载
            if (XyUtil.getBoolean(extend, DOWNLOAD_IN_THREAD_POOL, true)) {
                ThreadPoolManager.NUMBER_LOGO_DOWNLAOD.execute(new Runnable() {

                    @Override
                    public void run() {
                        downLogoFile(ctx, serverUrl, logoName, callBack);
                    }
                });
                XyUtil.doXycallBackResult(callBack, CallBackState.CURRENT_THREAD_NEED_DOWNLOAD, logoName);
            } else {
                // 在当前线程执行下载
                file = downLogoFile(ctx, serverUrl, logoName, callBack);
            }
            return file;
        } catch (Throwable e) {
            LogManager.e(Constant.TAG, "NumberLogoUtil findLogoFile error:", e);
            XyUtil.doXycallBackResult(callBack, CallBackState.ERROR, logoName, e.getMessage());
        }
        return null;
    }
    /*SDK-637 zhaojiangwei 20160929 start*/
    private static File getLocalLogoFile(String logoName) {
//        File file = new File(Constant.getPath(Constant.DUOQU_NUMBER_LOGO_DIR) + logoName);
        File file = new File(Constant.getPath("duoqu_publiclogo") + logoName);
        //LogManager.e("immo", "logo path:"+file.getAbsolutePath());
        if (file.exists()) {
            return file;
        }
        return null;
    }
    /*SDK-637 zhaojiangwei 20160929 end*/
    /**
     * 
     * @param ctx
     * @param serverUrl
     * @param logoName 图片名称
     * @param callBack 
     *            index0(状态):
     *                  CallBackState.DOWNLOAD_COMPLETE:当前线程或新线程，成功下载文件
     *                  CallBackState.DOWNLOAD_FAILED:当前线程或新线程，文件下载失败
     *                  CallBackState.ERROR:当前线程或新线程，存在异常，文件下载失败
     *            index1:logoName
     *            index2:
     *                  (index0 == CallBackState.DOWNLOAD_COMPLETE):文件的File对象
     *                  (index0 == CallBackState.DOWNLOAD_FAILED):"download failed"
     *                  (index0 == CallBackState.ERROR):String类型 异常信息
     * @return
     */
    private static File downLogoFile(Context ctx, String serverUrl, String logoName, final XyCallBack callBack) {
        // 只有我们自己服务器上的logo图片需要进行MD5校验，因为我们服务器上的图片文件是以MD5命名；联盟logo及联盟提供的图片不一定以MD5命名图片文件，所以不需要进行MD5校验
        boolean checkMD5 = !isUnionLogo(logoName) && !isUnionServer(serverUrl);
        /*SDK-637 zhaojiangwei 20160929 start*/
        File file = FileUtils.downFile(ctx, serverUrl, logoName, Constant.getPath(Constant.DUOQU_PUBLIC_LOGO_DIR),
        /*SDK-637 zhaojiangwei 20160929 end*/
                checkMD5, new XyCallBack() {

                    @Override
                    public void execute(Object... obj) {
                        try {
                            if (obj != null && obj.length > 0 && ((Integer) obj[0]) == CallBackState.DOWNLOAD_COMPLETE) {
                                // 如果下载成功删除LAST_DOWNLOAD_LOGO_TIME对应的logo名称数据，
                                // 因为已经不许要通过LAST_DOWNLOAD_LOGO_TIME来防止重复请求下载，
                                removeLastDownloadLogoTime((File) obj[2]);
                            }
                        } catch (Throwable e) {
                            LogManager.e(Constant.TAG,
                                    "NumberLogoUtil downLogoFile execute error:", e);
                        }
                        // 回调结果
                        XyUtil.doXycallBackResult(callBack, obj);
                    }
                });
        return file;
    }

    private static XyCallBack downLogoFileCallBack(final String num, final XyCallBack callBack) {
        return new XyCallBack() {

            @Override
            public void execute(Object... obj) {
                try {
                    // 将参数2由logoName替换为num
                    obj[1] = num;
                } catch (Exception ex) {
                }
                XyUtil.doXycallBackResult(callBack, obj);
            }
        };
    }

    private static boolean addLastDownloadLogoTime(String logoName) {
        synchronized (LAST_DOWNLOAD_LOGO_TIME) {
            Long time = LAST_DOWNLOAD_LOGO_TIME.get(logoName);
            if (time == null || time + Constant.MINUTE < System.currentTimeMillis()) {
                LAST_DOWNLOAD_LOGO_TIME.put(logoName, System.currentTimeMillis());
                return true;
            }
            return false;
        }
    }

    /**
     * 删除LAST_DOWNLOAD_LOGO_TIME Map内指定logo名称的数据
     * 
     * @param file
     */
    private static void removeLastDownloadLogoTime(File file) {
        if (file == null || !file.exists()) {
            return;
        }
        synchronized (LAST_DOWNLOAD_LOGO_TIME) {
            LAST_DOWNLOAD_LOGO_TIME.remove(file.getName());
        }
    }
}
/* SDK-428 huangzhiqiang 20160615 end */